/*
 *所有关于MaterialCatalog类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*MaterialCatalogService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using StackExchange.Redis;
using System.Linq;
using System.Linq.Expressions;
using VOL.Core.BaseProvider;
using VOL.Core.Extensions;
using VOL.Core.Extensions.AutofacManager;
using VOL.Core.Utilities;
using VOL.Domain.Dto;
using VOL.Domain.Infrastructure;
using VOL.Domain.IRepositories;
using VOL.Entity.DomainModels;

namespace VOL.Domain.Services
{
    /// <summary>
    /// 111
    /// </summary>
    public partial class MaterialCatalogService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IBaseRepository<MaterialCatalog> _materialBaseRepository;
        private readonly IConnectionMultiplexer _redis;
        private readonly IMaterialCatalogRepository _repository;//访问数据库

        [ActivatorUtilitiesConstructor]
        public MaterialCatalogService(
            IMaterialCatalogRepository dbRepository,
            IHttpContextAccessor httpContextAccessor,
            IBaseRepository<MaterialCatalog> materialBaseRepository,
            IConnectionMultiplexer redis
            )
        : base(dbRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            this._materialBaseRepository = materialBaseRepository;
            this._redis = redis;
            _repository = dbRepository;
         
            //多租户会用到这init代码，其他情况可以不用
            //base.Init(dbRepository);
        }




    public List<MaterialCatalogTreeDto> BuildTree(List<MaterialCatalogTreeDto> nodes, int parentId = 0)
        {
            return nodes
                .Where(x => x.ParentId == parentId)
                .OrderBy(x => x.OrderById)
                .Select(x => {
                    x.Children = BuildTree(nodes, x.Id);
                    return x;
                })
                .ToList();
        }
        //public async Task<List<MaterialCatalogTreeDto>> GetMaterialCatalogTreeAsync()
        //{
        //    // 查询所有数据
        //    var list = await _materialBaseRepository
        //        .GetAll()
        //        .OrderBy(x => x.OrderById)
        //        .ToListAsync();

        //    // 映射为DTO
        //    var dtoList = list.Select(x => new MaterialCatalogTreeDto
        //    {
        //        Id = x.Id,
        //        ClassifyName = x.ClassifyName,
        //        OrderById = x.OrderById??0,
        //        MaterialName = x.MaterialName,
        //        Status = x.Status ?? 0,
        //        CreateTime = x.CreateTime ??DateTime.MinValue,
        //        ParentId = x.ParentId ?? 0
        //    }).ToList();

        //    // 组装树形结构
        //    return BuildTree(dtoList, 0);
        //}


        public async Task<List<MaterialCatalogTreeDto>> GetMaterialCatalogTreeAsync()
        {
            var db = _redis.GetDatabase();
            string cacheKey = "MaterialCatalogTree";

            // 1. 优先查Redis
            var cacheValue = await db.StringGetAsync(cacheKey);
            if (!cacheValue.IsNullOrEmpty)
            {
                var cachedList = JsonConvert.DeserializeObject<List<MaterialCatalogTreeDto>>(cacheValue);
                // ⚠️别直接返回，需要构建树
                return BuildTree(cachedList, 0);
            }

            // 2. Redis没有，查数据库
            var list = await _materialBaseRepository
                .GetAll()
                .OrderBy(x => x.OrderById)
                .ToListAsync();

            var dtoList = list.Select(x => new MaterialCatalogTreeDto
            {
                Id = x.Id,
                ClassifyName = x.ClassifyName,
                OrderById = x.OrderById ?? 0,
                MaterialName = x.MaterialName,
                Status = x.Status ?? 0,
                CreateTime = x.CreateTime ?? DateTime.MinValue,
                ParentId = x.ParentId ?? 0
            }).ToList();

            // 3. 写入Redis
            string json = JsonConvert.SerializeObject(dtoList);
            await db.StringSetAsync(cacheKey, json, TimeSpan.FromHours(1)); // 缓存1小时

            // 4. 返回
            return BuildTree(dtoList, 0);
        }

        public async Task<WebResponseContent> CreateUpdateMaterialCatalog(MaterialCatalog materialCatalog)
        {
            var result = new WebResponseContent();
            if (materialCatalog.Id != 0)
            {
                var material = _materialBaseRepository.GetAll().FirstOrDefault(a => a.Id == materialCatalog.Id);
                material.ClassifyName = materialCatalog.ClassifyName;
                material.OrderById = materialCatalog.OrderById;
                material.MaterialName = materialCatalog.MaterialName;
                material.Status = materialCatalog.Status;
                material.CreateTime = materialCatalog.CreateTime;
                material.ParentId = materialCatalog.ParentId;
                var entity = await _materialBaseRepository.Update(material);
            }
            else
            {
                var entity = await _materialBaseRepository.Add(materialCatalog);
            }
            return result.OK("成功");
        }


        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> DeleteMaterialCatalogAsync(int id)
        {
            try
            {
                // 获取要删除的分类及其所有子分类
                var rootCatalog = await _materialBaseRepository.GetAll()
                    .FirstOrDefaultAsync(c => c.Id == id);

                if (rootCatalog == null)
                    return false;

                // 查找所有子分类（递归获取所有层级）
                var allChildIds = await GetAllChildIds(id);

                // 添加根节点ID
                allChildIds.Add(id);

                // 查询所有需要删除的分类
                var catalogsToDelete = await _materialBaseRepository.GetAll()
                    .Where(c => allChildIds.Contains(c.Id))
                    .ToListAsync();

                // 删除所有相关分类
                await _materialBaseRepository.DeleteRang(catalogsToDelete);


                return true;
            }
            catch (Exception)
            {
                // 记录日志
                return false;
            }
        }

        /// <summary>
        /// 递归获取所有子ID
        /// </summary>
        /// <param name="parentId"></param>
        /// <returns></returns>
        private async Task<List<int>> GetAllChildIds(int parentId)
        {
            var result = new List<int>();

            // 获取直接子类
            var directChildren = await _materialBaseRepository.GetAll()
                .Where(c => c.ParentId == parentId)
                .Select(c => c.Id)
                .ToListAsync();

            result.AddRange(directChildren);

            // 递归获取每个子类的子类
            foreach (var childId in directChildren)
            {
                var grandChildrenIds = await GetAllChildIds(childId);
                result.AddRange(grandChildrenIds);
            }

            return result;
        }






        public async Task<WebResponseContent> GetMaterialCatalog()
        {
            var response = new WebResponseContent();
            try
            {
                // 获取所有分类数据
                var allCatalogs = await _materialBaseRepository.GetAll()
                    .OrderBy(x => x.OrderById)
                    .ToListAsync();

                if (!allCatalogs.Any())
                {
                    return response.Error("未找到物料分类数据");
                }

                // 首先获取所有根节点（ParentId为null或0的节点）
                var rootNodes = allCatalogs.Where(x => !x.ParentId.HasValue || x.ParentId == 0).ToList();
                if (!rootNodes.Any())
                {
                    // 如果没有根节点，尝试获取所有节点作为根节点
                    rootNodes = allCatalogs.ToList();
                }

                var treeData = new List<TreeNode>();
                foreach (var root in rootNodes)
                {
                    var node = new TreeNode
                    {
                        Id = root.Id,
                        Label = root.ClassifyName ?? "",
                        MaterialName = root.MaterialName ?? "",
                        Status = root.Status,
                        OrderById = root.OrderById ?? 0,
                        ParentId = root.ParentId,
                        CreateTime = root.CreateTime
                    };

                    // 获取子节点
                    node.Children = GetChildNodes(allCatalogs, root.Id);
                    treeData.Add(node);
                }

                // 按OrderById排序
                treeData = treeData.OrderBy(x => x.OrderById).ToList();

                return response.OK(null, treeData);
            }
            catch (Exception ex)
            {
                return response.Error($"获取物料分类失败：{ex.Message}");
            }
        }

        private List<TreeNode> GetChildNodes(List<MaterialCatalog> allCatalogs, int parentId)
        {
            var children = allCatalogs
                .Where(x => x.ParentId == parentId)
                .OrderBy(x => x.OrderById)
                .ToList();

            var nodes = new List<TreeNode>();
            foreach (var child in children)
            {
                var node = new TreeNode
                {
                    Id = child.Id,
                    Label = child.ClassifyName ?? "",
                    MaterialName = child.MaterialName ?? "",
                    Status = child.Status,
                    OrderById = child.OrderById ?? 0,
                    ParentId = child.ParentId,
                    CreateTime = child.CreateTime
                };

                // 递归获取子节点
                node.Children = GetChildNodes(allCatalogs, child.Id);
                nodes.Add(node);
            }

            return nodes;
        }
    }

    public class TreeNode
    {
        public int Id { get; set; }
        public string Label { get; set; }
        public string MaterialName { get; set; }
        public int? Status { get; set; }
        public int OrderById { get; set; }
        public int? ParentId { get; set; }
        public DateTime? CreateTime { get; set; }
        public List<TreeNode> Children { get; set; } = new List<TreeNode>();
    }
}
